[blackwell_kihlstrom.md] Update np.random → Generator API#890
[blackwell_kihlstrom.md] Update np.random → Generator API#890Chihiro2000GitHub wants to merge 1 commit into
Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
📖 Netlify Preview Ready!Preview URL: https://pr-890--sunny-cactus-210e3e.netlify.app Commit: 📚 Changed LecturesBuild Info
|
mmcky
left a comment
There was a problem hiding this comment.
Thanks @Chihiro2000GitHub! The migration is correct and behaviour-preserving. Just one optional consistency nit inline about aligning sample_posteriors with the seed-based pattern already used by sequential_update / check_martingale_mean in this lecture. Otherwise good to go. (Worth a quick look at the Netlify preview to confirm the simplex clouds still read well, since the seeded stream changes under Generator.)
@HumphreyYang — could you weigh in on the inline suggestion? It's a judgment call about which RNG idiom to standardise on within a lecture (module-level rng vs. seed-per-function), so I'd like your read before we ask for changes.
| name: fig-blackwell-simplex-clouds | ||
| --- | ||
| def sample_posteriors(μ_matrix, prior, n_draws=3000): | ||
| def sample_posteriors(μ_matrix, prior, n_draws=3000, rng=rng): |
There was a problem hiding this comment.
Thanks @Chihiro2000GitHub — this is correct and faithfully preserves the original behaviour (the two sample_posteriors calls still draw sequentially from a single stream).
One small consistency point: this lecture already has two sibling functions, sequential_update and check_martingale_mean, that take a seed and build the generator locally (rng = np.random.default_rng(seed)). With this change sample_posteriors instead relies on a module-level rng injected via a rng=rng default argument, so the lecture ends up with two different RNG idioms for three very similar functions.
Could we align sample_posteriors with its siblings by building the generator in the driver (plot_simplex_posteriors) and passing it in? That keeps a single shared stream (so the μ and ν clouds stay independent, as now), removes the module-level global, and lets us drop the np.random.seed(0) line at the top. Something like:
def sample_posteriors(μ_matrix, prior, n_draws=3000, rng=None):
"""..."""
if rng is None:
rng = np.random.default_rng()
N, M = μ_matrix.shape
states = rng.choice(N, size=n_draws, p=prior)
signals = np.array([rng.choice(M, p=μ_matrix[s]) for s in states])
...and then in plot_simplex_posteriors:
def plot_simplex_posteriors(μ_matrix, ν_matrix, prior3, n_draws=3000, seed=0):
rng = np.random.default_rng(seed)
posts_μ = sample_posteriors(μ_matrix, prior3, n_draws, rng)
posts_ν = sample_posteriors(ν_matrix, prior3, n_draws, rng)
...With that, the rng = np.random.default_rng(0) line in the imports block can be removed. Non-blocking — happy either way, but it would make the three functions consistent.
There was a problem hiding this comment.
Many thanks @mmcky, that makes sense.
I agree that creating the generator locally in plot_simplex_posteriors is
cleaner and keeps the RNG pattern consistent with sequential_update and
check_martingale_mean.
Changing to
posts_μ = sample_posteriors(μ_matrix, prior3, n_draws, rng=rng)
posts_ν = sample_posteriors(ν_matrix, prior3, n_draws, rng=rng)also makes it explicit that both posterior samples are drawn using the same
local generator.
After making this change, we can drop the global
rng = np.random.default_rng(0)because it was only being used as the default value for rng in
sample_posteriors.
I think it is a strict improvement and should be adopted everywhere else!
There was a problem hiding this comment.
Thank you both! I'll go through your comments later, probably this weekend.
Summary
This PR migrates legacy NumPy random API usage in
blackwell_kihlstrom.mdas part of QuantEcon/meta#299.Details
np.random.seed(0)withrng = np.random.default_rng(0)in the imports block.sample_posteriorsto acceptrng=rngas a default argument and replaced the two internalnp.random.choice(...)calls withrng.choice(...).sample_posteriorsare unchanged — the module-levelrngis used by default.sequential_updateandcheck_martingale_meanwere already using the Generator API and required no changes.np.random.seed(0)already provided.Hi @mmcky and @HumphreyYang, I'd be grateful if you could take a look when you have time.